package com.yunfinal.api.tpl.template.directive.db;

import com.jfinal.core.Controller;
import com.jfinal.plugin.activerecord.DbPro;
import com.jfinal.plugin.activerecord.SqlPara;
import com.jfinal.template.Env;
import com.jfinal.template.io.Writer;
import com.jfinal.template.stat.Ctrl;
import com.jfinal.template.stat.Scope;

/**
 * #sqlPara 指令方便定义SqlPara  https://www.jfinal.com/doc/5-13
 * https://jfinal.com/doc/5-6
 * <p>
 * 定义：变量名是必须的，其他字段非必填有默认值
 * #paginate(Page<Record>变量名, pageNumber=1, pageSize=20, isGroupBySql=true)
 * 在此是SQL模版语法
 * #end
 * <p>
 * @author  杜福忠
 */
public class PaginateDirective extends SqlParaDirective {
    protected int pageNumber = 1;
    protected int pageSize = 15;
    protected boolean isGroupBySql = false;
    protected static String key_pageNumber = "pageNumber";
    protected static String key_pageSize = "pageSize";

    @Override
    public void exec(Env env, Scope scope, Writer writer) {
        evalAssignExpression(scope);
        Object aThis = scope.get("this");
        if(aThis != null && aThis instanceof Controller){
            Controller c = (Controller) aThis;
            this.pageNumber = getInt(scope, c, key_pageNumber, this.pageNumber);
            this.pageSize = getInt(scope, c, key_pageSize, this.pageSize);
            this.isGroupBySql = getBoolean(scope, c, "isGroupBySql", isGroupBySql);
        }
        setDefaultName("page");
        super.exec(env, scope, writer);
    }

    @Override
    protected Object getData(DbPro db, SqlPara sqlPara) {
        return db.paginate(pageNumber, pageSize, isGroupBySql, sqlPara);
    }

    private Integer getInt(Scope scope, Controller c, String key, Integer defaultValue) {
        Object obj = scope.getLocal(key);
        if(obj == null){
            obj = c.getInt(key);
        }
        if(obj == null){
            return defaultValue;
        }
        if(obj instanceof Integer){
            return (Integer)obj;
        }
        return Integer.valueOf(obj.toString());
    }
    private Boolean getBoolean(Scope scope, Controller c, String key, Boolean defaultValue) {
        Object obj = scope.getLocal(key);
        if(obj == null){
            obj = c.getBoolean(key);
        }
        if(obj == null){
            return defaultValue;
        }
        if(obj instanceof Boolean){
            return (Boolean)obj;
        }
        return Boolean.valueOf(obj.toString());
    }

    private void evalAssignExpression(Scope scope) {
        if (exprArray.length > 1){
            return;
        }
        Ctrl ctrl = scope.getCtrl();
        try {
            ctrl.setLocalAssignment();
            for (int i=1; i<exprArray.length; i++) {
                exprArray[i].eval(scope);
            }
        } finally {
            ctrl.setWisdomAssignment();
        }
    }

    public static void setPageKey(String key_pageNumber, String key_pageSize) {
        PaginateDirective.key_pageNumber = key_pageNumber;
        PaginateDirective.key_pageSize = key_pageSize;
    }

}
